home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
Box.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-29
|
8KB
|
406 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "Box.h"
#include "Class.h"
#include "Collection.h"
#include "Math.h"
struct rcinfo {
int wd, ht, bs;
int hfixed, vfixed;
};
//---- Box ---------------------------------------------------------------------
NewMetaImpl(Box,CompositeVObject, (T(colsrows), T(gap), TE(align)));
Box::Box(int id, Point cr, Point g, VObjAlign a)
: CompositeVObject(id, (SeqCollection*)0)
{
colsrows= cr;
gap= g;
align= a;
}
Box::Box(int id, Point cr, Point g, VObjAlign a, VObject *va_(vop), ...)
: CompositeVObject(id, (SeqCollection*)0)
{
va_list ap;
va_start(ap, va_(vop));
SetItems(va_(vop), ap);
colsrows= cr;
gap= g;
align= a;
va_end(ap);
}
Box::Box(int id, Point cr, Point g, VObjAlign a, SeqCollection *sc)
: CompositeVObject(id, sc)
{
colsrows= cr;
gap= g;
align= a;
}
Box::Box(int id, Point cr, Point g, VObjAlign a, va_list ap)
: CompositeVObject(id, ap)
{
colsrows= cr;
gap= g;
align= a;
}
void Box::SetAlign(VObjAlign a)
{
align= a;
}
void Box::SetGap(Point g)
{
gap= g;
}
void Box::SetColsRowsSize(Point cr)
{
colsrows= cr;
}
int Box::expandCnt()
{
return 0;
}
Point Box::ColsRowsSize()
{
int n= Size();
if (colsrows.y <= 0 && colsrows.x <= 0) {
int c= Math::Sqrt(n);
return Point(c, (n-1)/c+1);
}
if (colsrows.y <= 0)
return Point(colsrows.x, (n-1)/colsrows.x+1);
if (colsrows.x <= 0)
return Point((n-1)/colsrows.y+1, colsrows.y);
return colsrows;
}
Metric Box::getMinSize(Point &rc, rcinfo *rci)
{
register int x, y;
Point total(-gap);
getGrid(rc, rci);
for (x= 0; x < rc.x; x++)
total.x+= rci[x].wd+gap.x;
for (y= 0; y < rc.y; y++)
total.y+= rci[y].ht+gap.y;
if (align & eVObjVBase)
return Metric(total, rci[0].bs);
if (Size() > 0)
return Metric(total, At(0)->Base());
return Metric(total);
}
void Box::getGrid(Point &rc, rcinfo *rci)
{
Iter next(MakeIterator());
register VObject *vop;
register int x, y, hh, bb, maxwd= 0, maxht= 0, n;
Metric m;
bool hexpand= align & eVObjHExpand,
vexpand= (align & eVObjVExpand) && !(align & eVObjVBase);
for (x= 0; x < rc.x; x++)
rci[x].hfixed= 0;
for (y= 0; y < rc.y; y++)
rci[y].vfixed= 0;
for (y= 0; y < rc.y; y++) {
hh= bb= 0;
for (x= 0; x < rc.x; x++) {
if (vop= (VObject*) next()) {
m= vop->GetMinSize();
if (align & eVObjVBase) {
hh= Math::Max(hh, m.Base());
int eb= m.Height()-m.Base();
bb= Math::Max(bb, eb);
} else {
hh= Math::Max(hh, m.extent.y);
}
rci[x].wd= Math::Max(rci[x].wd, m.Width());
maxwd= Math::Max(maxwd, m.Width());
if (!hexpand || vop->TestFlag(eVObjHFixed))
rci[x].hfixed++;
if (!vexpand || vop->TestFlag(eVObjVFixed))
rci[y].vfixed++;
}
}
rci[y].ht= hh+bb;
rci[y].bs= hh;
maxht= Math::Max(maxht, hh+bb);
}
for (x= 0; x < rc.x; x++) {
if (rci[x].hfixed >= rc.y)
rci[x].hfixed= 1;
else
rci[x].hfixed= 0;
}
for (y= 0; y < rc.y; y++) {
if (rci[y].vfixed >= rc.x)
rci[y].vfixed= 1;
else
rci[y].vfixed= 0;
}
/*
for (x= 0; x < rc.x; x++) {
if (rci[x].hfixed > 0)
rci[x].hfixed= 1;
else
rci[x].hfixed= 0;
}
for (y= 0; y < rc.y; y++) {
if (rci[y].vfixed > 0)
rci[y].vfixed= 1;
else
rci[y].vfixed= 0;
}
*/
if ((align & eVObjHGapExpand) && rc.x > 1) {
ResetFlag(eVObjHFixed);
} else {
for (n= x= 0; x < rc.x; x++)
if (rci[x].hfixed)
n++;
SetFlag(eVObjHFixed, n >= rc.x);
}
if ((align & eVObjVGapExpand) && rc.y > 1) {
ResetFlag(eVObjVFixed);
} else {
for (n= y= 0; y < rc.y; y++)
if (rci[y].vfixed)
n++;
SetFlag(eVObjVFixed, n >= rc.y);
}
if (align & eVObjHEqual)
for (x= 0; x < rc.x; x++)
rci[x].wd= maxwd;
if (align & eVObjVEqual)
for (y= 0; y < rc.y; y++)
rci[y].ht= maxht;
}
void Box::expand(Point &rc, rcinfo *rci, Point &g, Point &r)
{
register x, y, div, rest;
int n;
g= gap;
r= gPoint0;
Point diff= GetExtent()-getMinSize(rc, rci).extent;
if (diff.x > 0) {
if (align & eVObjHGapExpand) {
if (rc.x > 1) {
g.x= diff.x/(rc.x-1);
r.x= diff.x-g.x*(rc.x-1);
g.x+= gap.x;
}
}
if (align & eVObjHExpand) {
for (n= x= 0; x < rc.x; x++)
if (!rci[x].hfixed) // col not hfixed
n++;
if (n > 0) {
div= diff.x/n;
rest= diff.x-div*n;
for (x= 0; x < rc.x; x++) {
if (!rci[x].hfixed) {
rci[x].wd+= div;
if (rest > 0) {
rci[x].wd++;
rest--;
}
}
}
}
}
}
if (diff.y > 0) {
if (align & eVObjVGapExpand) {
if (rc.y > 1) {
g.y= diff.y/(rc.y-1);
r.y= diff.y-g.y*(rc.y-1);
g.y+= gap.y;
}
}
if (align & eVObjVExpand) {
for (n= y= 0; y < rc.y; y++)
if (!rci[y].vfixed) // row not vfixed
n++;
if (n > 0) {
div= diff.y/n;
rest= diff.y-div*n;
for (y= 0; y < rc.y; y++) {
if (!rci[y].vfixed) {
rci[y].ht+= div;
if (rest > 0) {
rci[y].ht++;
rest--;
}
}
}
}
}
}
}
Metric Box::GetMinSize()
{
Point rc= ColsRowsSize();
rcinfo *rci= new rcinfo[Math::Max(rc.x, rc.y)];
Metric m= getMinSize(rc, rci);
delete rci;
return m;
}
void Box::SetOrigin(Point at)
{
Iter next(MakeIterator());
register VObject *vop;
register int x, y;
Point g, r, rr, a, rc= ColsRowsSize();
rcinfo *rci= new rcinfo[Math::Max(rc.x, rc.y)];
expand(rc, rci, g, r);
VObject::SetOrigin(at);
a.y= at.y;
rr.y= r.y;
for (y= 0; y < rc.y; y++) {
a.x= at.x;
rr.x= r.x;
for (x= 0; x < rc.x; x++) {
if (vop= (VObject*) next())
vop->Align(a, Metric(rci[x].wd, rci[y].ht, rci[y].bs), align);
a.x+= rci[x].wd + g.x;
if (rr.x > 0) {
a.x++;
rr.x--;
}
}
a.y+= rci[y].ht + g.y;
if (rr.y > 0) {
a.y++;
rr.y--;
}
}
delete rci;
}
void Box::SetExtent(Point ee)
{
Iter next(MakeIterator());
register VObject *vop;
register x, y;
Point e, g, r, rc= ColsRowsSize();
rcinfo *rci= new rcinfo[Math::Max(rc.x, rc.y)];
bool hexpand= align & (eVObjHExpand|eVObjHEqual),
vexpand= (align & (eVObjVExpand|eVObjVEqual)) && !(align & eVObjVBase);
e= getMinSize(rc, rci).extent;
if (!TestFlag(eVObjHFixed))
e.x= ee.x;
if (!TestFlag(eVObjVFixed) && !(align & eVObjVBase))
e.y= ee.y;
VObject::SetExtent(e);
expand(rc, rci, g, r);
for (y= 0; y < rc.y; y++)
for (x= 0; x < rc.x; x++)
if (vop= (VObject*) next()) {
e= vop->GetMinSize().extent;
if (hexpand && !vop->TestFlag(eVObjHFixed))
e.x= rci[x].wd;
if (vexpand && !vop->TestFlag(eVObjVFixed))
e.y= rci[y].ht;
vop->SetExtent(e);
}
delete rci;
}
void Box::DrawAll(Rectangle r, bool highlight)
{
CompositeVObject::DrawAll(r, highlight);
}
OStream& Box::PrintOn(OStream &s)
{
CompositeVObject::PrintOn(s);
return s << colsrows SP << gap SP << align SP;
}
IStream& Box::ReadFrom(IStream &s)
{
CompositeVObject::ReadFrom(s);
return s >> colsrows >> gap >> Enum(align);
}
//---- HBox --------------------------------------------------------------------
NewMetaImpl0(HBox,Box);
HBox::HBox(Point g, VObjAlign a) : Box(cIdNone, Point(0,1), g, a)
{
}
HBox::HBox(Point g, VObjAlign a, VObject *va_(vop), ...)
: Box(cIdNone, Point(0,1), g, a)
{
va_list ap;
va_start(ap, va_(vop));
SetItems(va_(vop), ap);
va_end(ap);
}
HBox::HBox(Point g, VObjAlign a, SeqCollection *c)
: Box(cIdNone, Point(0,1), g, a, c)
{
}
//---- VBox --------------------------------------------------------------------
NewMetaImpl0(VBox,Box);
VBox::VBox(Point g, VObjAlign a) : Box(cIdNone, Point(1,0), g, a)
{
}
VBox::VBox(Point g, VObjAlign a, VObject *va_(vop), ...)
: Box(cIdNone, Point(1,0), g, a)
{
va_list ap;
va_start(ap, va_(vop));
SetItems(va_(vop), ap);
va_end(ap);
}
VBox::VBox(Point g, VObjAlign a, SeqCollection *c)
: Box(cIdNone, Point(0,1), g, a, c)
{
}